package com.zzh.camera2.presenter

import android.content.Context
import android.graphics.Bitmap
import android.os.Build
import android.os.Environment
import android.util.Log
import com.zzh.camera2.manager.*
import com.zzh.camera2.model.CameraParameter
import com.zzh.camera2.ui.AutoFitTextureView
import com.zzh.camera2.model.Const
import com.zzh.camera2.utils.ImageUtils
import com.zzh.camera2.utils.JavaUtils
import com.zzh.camera2.utils.NV21ToBitmap
import java.io.File

class MainPresenter : MainContract.Presenter, ICameraPreviewCallback {
    private var view: MainContract.View

    // manage first camera
    lateinit var cameraManager: ICameraManager

    // manage second camera
    lateinit var cameraManager2: ICameraManager
    var nv21ToBitmap: NV21ToBitmap? = null
    var isTakePhoto = false
    var isTakePhoto2 = false
    private var isShowPreviewView = CameraParameter.isShowPreviewView

    constructor(context: Context, view: MainContract.View) {
        this.view = view
        initCameraManager(context)
    }

    private fun initCameraManager(context: Context) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP
            || CameraParameter.useApiVersion == CameraParameter.API_VERSION_1
        ) {
            cameraManager = CameraApi1Manager()
            cameraManager2 = CameraApi1Manager()
            view!!.setCameraApiVersion("1")
        } else {
            cameraManager = CameraApi2Manager(context)
            cameraManager2 = CameraApi2Manager(context)
            view!!.setCameraApiVersion("2")
        }
        cameraManager.setPreviewCallback(this)
        cameraManager2.setPreviewCallback(this)
    }

    override fun openCamera(
        textureView: AutoFitTextureView,
        cameraId: Int,
        previewWidth: Int,
        previewHeight: Int,
        previewFormat: Int
    ) {
        if (isShowPreviewView) {
            cameraManager.openCamera(
                textureView,
                cameraId,
                previewWidth,
                previewHeight,
                previewFormat
            )
        } else {
            cameraManager.openCamera(cameraId, previewWidth, previewHeight, previewFormat)
        }
    }

    override fun openCamera2(
        textureView: AutoFitTextureView,
        cameraId: Int,
        previewWidth: Int,
        previewHeight: Int,
        previewFormat: Int
    ) {
        if (isShowPreviewView) {
            cameraManager2.openCamera(
                textureView,
                cameraId,
                previewWidth,
                previewHeight,
                previewFormat
            )
        } else {
            cameraManager2.openCamera(cameraId, previewWidth, previewHeight, previewFormat)
        }
    }

    override fun startPreview() {
        cameraManager.startPreview()
    }

    override fun startPreview2() {
        cameraManager2.startPreview()
    }

    override fun stopPreview() {
        cameraManager.stopPreview()
    }

    override fun stopPreview2() {
        cameraManager2.stopPreview()
    }

    override fun releaseCamera() {
        cameraManager.releaseCamera()
    }

    override fun releaseCamera2() {
        cameraManager2.releaseCamera()
    }

    // data format mast be nv21
    override fun onPreviewFrame(
        data: ByteArray?,
        convertedImageFormat: Int,
        cameraManager: ICameraManager
    ) {
        try {
            var bitmap: Bitmap? = null

            if (data == null) {
                return
            }
            // 获取bitmap
            if (convertedImageFormat == Const.previewImageFormatNV21) {
                if (nv21ToBitmap == null) {
                    nv21ToBitmap = NV21ToBitmap(view!!.getAcContext())
                }
                bitmap = nv21ToBitmap!!.nv21ToBitmap(data, Const.previewWidth, Const.previewHeight)
            } else if (convertedImageFormat == Const.previewImageFormatRAW16) {
                // display ir use ir raw data
                val irArgbData: IntArray = JavaUtils.getIrARGB(data, Const.previewWidth, Const.previewHeight)
                bitmap = Bitmap.createBitmap(
                    Const.previewWidth,
                    Const.previewHeight,
                    Bitmap.Config.ARGB_8888
                )
                bitmap.setPixels(
                    irArgbData,
                    0,
                    Const.previewWidth,
                    0,
                    0,
                    Const.previewWidth,
                    Const.previewHeight
                )
            }

            bitmap ?: return

            if (cameraManager == this.cameraManager) {
                val rotateBitmap = bitmap//ImageUtils.adjustPhotoRotation(bitmap, 90)
                if (isTakePhoto) {
                    isTakePhoto = false
                    savePhoto(rotateBitmap, "camera1_")
                }
                view!!.onPreviewCallback(rotateBitmap)
            } else if (cameraManager == this.cameraManager2) {
                val rotateBitmap = bitmap//ImageUtils.adjustPhotoRotation2(bitmap, 270)
                if (isTakePhoto2) {
                    isTakePhoto2 = false
                    savePhoto(rotateBitmap!!, "camera2_")
                }
                view!!.onPreviewCallback2(rotateBitmap)
            }
        } catch (e: Exception) {
            Log.w("MainPresenter", "onPreviewCallback e=$e")
        }
    }

    override fun takePhoto() {
        if (!CameraParameter.isShowCallbackImage) {
            view!!.showToast("因设置为不显示预览回调图像，无法保存图像，保存失败")
            return
        }
        isTakePhoto = true
    }

    override fun takePhoto2() {
        if (!CameraParameter.isShowCallbackImage) {
            view!!.showToast("因设置为不显示预览回调图像，无法保存图像，保存失败")
            return
        }
        isTakePhoto2 = true
    }

    private fun savePhoto(bitmap: Bitmap, namePrefix: String) {
        val file = File(
            Environment.getExternalStorageDirectory(),
            namePrefix + System.currentTimeMillis().toString() + ".jpg"
        )
        val success = ImageUtils.saveBitmap(file, bitmap)
        view!!.showToast(if (success) "保存图片成功，路径=" + file.absolutePath else "保存图片失败")
    }
}